﻿using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Service.Validation.BusinessRules;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;

namespace Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessLogic.BusinessRulesValidation
{
    public class ValidadorAlteracaoOrdem : BaseBusinessRuleValidation<BusinessEntity.Ordem>, IBusinessRuleValidation
    {
        #region Campos

        private Cliente.BusinessEntity.Cliente _cliente;
        private BusinessEntity.Ordem _ordemOriginal;
        private ResourceAccess.ManutencaoOrdens raManutencaoOrdens;
        private Movimento.BusinessEntity.InformacoesMovimento _informacoesMovimento;

        #region Erros

        private int ATIVO_NAO_POP = 109320;
        private int ATIVO_NAO_INFORMADO_FINANCIAMENTO = 109441;
        private int ERRO_INESPERADO_GERAR_CODIGO_CASAMENTO = 109281;
        private int ATIVO_INEXISTENTE = 109252;
        private int USUARIO_NAO_AUTORIZADO_ALTERAR_ATIVO = 109440;
        private int ATIVO_NAO_INFORMADO = 109258;
        private int BOLSA_INEXISTENTE = 109266;
        private int CARTEIRA_INVALIDA = 109271;
        private int CARTEIRA_NAO_INFORMADA = 109442;
        private int ORDEM_ADMINISTRADA_CONCORRENTE = 109434;
        private int CLIENTE_INVALIDO = 109254;
        private int USUARIO_NAO_AUTORIZADO_ALTERAR_CLIENTE = 109433;
        private int CLIENTE_NAO_INFORMADO = 109253;
        private int DATA_INVALIDA = 109280;
        private int DOLAR_INVALIDO = 109273;
        private int PRAZO_VENCIMENTO_NEGATIVO = 109249;
        private int MERCADO_NAO_TERMO = 109439;
        private int OPERADOR_INVALIDO = 109445;
        private int USUARIO_BLOQUEADO = 109279;
        private int USUARIO_NAO_OPERADOR = 109277;
        private int PERCENTUAL_CORRETAGEM_INVALIDO = 109437;
        private int PERCENTUAL_CORRETAGEM_NAO_INFORMADO = 109436;
        private int ALTERACAO_PERCENTUAL_CORRETAGEM_NAO_PERMITIDO = 109435;
        private int PRECO_ORDEM_INVALIDO = 109268;
        private int QUANTIDADE_DIFEENTE_ZERO = 109272;
        private int QUANTIDADE_NAO_MULTIPL0 = 109312;
        private int ORDEM_REDUZIDA_E_DISTRIBUIDA = 109444;
        private int SOMA_QUANTIDADE_ANEXO_MAIOR_QUANTIDADE = 109315;
        private int QUANTIDADE_ANEXOV_MAIOR_IGUAL_ZERO = 109314;
        private int QUANTIDADE_ANEXOIV_MAIOR_IGUAL_ZERO = 109313;
        private int USUARIO_NAO_AUTORIZADO_ALTERAR_QUANTIDADE = 109443;
        private int ALTERACAO_SITUACAO_INVALIDA = 109431;
        private int ORDEM_ADMINISTRADA_CONCORRENTE_TIPO_ORDEM = 109438;
        private int INTERVALO_PERCENTUAL_FINANCIAMENTO_INCORRETO = 109274;
        private int VALOR_FINANCIAMENTO_NEGATIVO = 109275;
        private int ORDEM_CANCELADA = 109415;
        private int USUARIO_NAO_AUTORIZADO_ALTERAR_ORDEM = 109288;
        private int ERRO_INESPERADO_VERIFICAR_CLIENTE_BLOQUEADO = 109414;
        private int USUARIO_NAO_AUTORIZADO_ALTERAR_PERCENTUAL_CORRETAGEM = 109670;
        private int ADMINISTRADA_CONCORRENTE_MODIFICADA = 109432;

        #endregion Erros

        #endregion

        #region Propriedades

        public BusinessEntity.Ordem OrdemOriginal
        {
            get
            {
                return _ordemOriginal;
            }
            set
            {
                _ordemOriginal = value;
            }
        }

        #endregion

        #region Construtor

        public ValidadorAlteracaoOrdem()
        {
            Movimento.BusinessLogic.ControleMovimentoOrdens blControleMovimentoOrdens = new Movimento.BusinessLogic.ControleMovimentoOrdens();

            _informacoesMovimento = blControleMovimentoOrdens.ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());
            this.raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();
        }

        #endregion

        #region Métodos

        /// <summary>
        /// Configurar Ordem
        /// </summary>
        private void ConfigurarOrdem()
        {
            DateTime timeStamp;
            Calendario.BusinessLogic.Calendario calentario = new Calendario.BusinessLogic.Calendario();

            EntityToValidate.CodigoUsuario = AuthorizationContext.Current.UserId;

            if (DateTime.TryParse(calentario.ObterTimeStamp(), out timeStamp))
                EntityToValidate.TimeStamp = timeStamp;
        }

        /// <summary>
        /// Configurar Tipo de Distribuicao
        /// </summary>
        private void ConfigurarTipoDistribuicao()
        {
            if (_cliente == null)
                this.ObterCliente();
            
            //Verifica se cliente da ordem é administrado concorrente
            if (_cliente.IsAdministradoConcorrente)
            {
                //Verifica se ativo é POP
                if (!string.IsNullOrEmpty(EntityToValidate.CodigoISIN) && EntityToValidate.CodigoISIN.Substring(6, 2).Equals("PP"))
                    base.AddValidationError(ATIVO_NAO_POP);
                else
                    EntityToValidate.TipoDistribuicaoPermitida = BusinessEntity.Enum.TipoDistribuicaoPermitida.DiferenciadoAdministradoConcorrente;
            }
            else
            {
                //Verifica se ativo é POP
                if (!string.IsNullOrEmpty(EntityToValidate.CodigoISIN) && EntityToValidate.CodigoISIN.Substring(6, 2).Equals("PP"))
                    EntityToValidate.TipoDistribuicaoPermitida = BusinessEntity.Enum.TipoDistribuicaoPermitida.DiferenciadoPOP;
                else
                    EntityToValidate.TipoDistribuicaoPermitida = BusinessEntity.Enum.TipoDistribuicaoPermitida.Normal;
            }
        }

        /// <summary>
        /// Obter lista de erros
        /// </summary>
        public List<Infra.Common.Validation.ValidationError> GetErrors()
        {
            return base.ErrorsList;
        }

        /// <summary>
        /// Tratar exceções
        /// </summary>
        /// <param name="request"></param>
        private void TratarExcecoes(BusinessEntity.Resultado request)
        {
            if (string.IsNullOrEmpty(request.Argumentos))
                base.AddValidationError(request.CodigoErro);
            else
            {
                base.AddValidationError(request.CodigoErro, string.Empty, ErrorMessage.ConvertXmlArgumentsToParameters(request.Argumentos));
            }
        }

        /// <summary>
        /// Validar Ativo
        /// </summary>
        private bool ValidarAtivo()
        {
            Titulo.BusinessLogic.Titulo blTitulo = new Titulo.BusinessLogic.Titulo();
            BusinessEntity.Resultado resultado = null;
            Titulo.BusinessEntity.Titulo titulo = null;

            // Verifica se ordem é do tipo financiamento
            if (EntityToValidate.TipoOrdem.HasValue && EntityToValidate.TipoOrdem.Value == BusinessEntity.Enum.TipoOrdem.Financiamento)
            {
                //Verifica se ativo foi informado
                if (!string.IsNullOrEmpty(EntityToValidate.Ativo))
                    base.AddValidationError(ATIVO_NAO_INFORMADO_FINANCIAMENTO);
                else
                {
                    EntityToValidate.Ativo = null;
                    EntityToValidate.CodigoISIN = null;
                    EntityToValidate.CodigoCasamento = null;
                }
            }
            else
            {
                //Verifica se ativo foi informado
                if (!string.IsNullOrEmpty(EntityToValidate.Ativo))
                {
                    //Verifica se houve alteração no ativo
                    if (EntityToValidate.Ativo != _ordemOriginal.Ativo)
                    {
                        if (AuthorizationContext.Current.CheckUserAccess("APAP", "ORD"))
                        {
                            Titulo.BusinessEntity.Titulo request = new Titulo.BusinessEntity.Titulo
                            {
                                DataOrdem = EntityToValidate.DataOrdem,
                                Codigo = EntityToValidate.Ativo
                            };

                            //Obter título
                            titulo = blTitulo.ObterTitulo(request);

                            //Verifica se ativo informado existe
                            if (titulo != null)
                            {
                                //Atribui valor do Código ISIN do ativo para a ordem
                                EntityToValidate.CodigoISIN = titulo.CodigoISIN;

                                //Gera código do casamento para a ordem
                                resultado = raManutencaoOrdens.GerarCodigoCasamento(EntityToValidate);

                                if (!resultado.Sucesso)
                                {
                                    if (resultado.CodigoErro == -1)
                                        base.AddValidationError(ERRO_INESPERADO_GERAR_CODIGO_CASAMENTO);
                                    else
                                        this.TratarExcecoes(resultado);
                                }
                                else
                                {
                                    EntityToValidate.CodigoCasamento = resultado.Valor.ToString();
                                }
                            }
                            else
                                base.AddValidationError(ATIVO_INEXISTENTE);
                        }
                        else
                            base.AddValidationError(USUARIO_NAO_AUTORIZADO_ALTERAR_ATIVO);
                    }
                }
                else
                    base.AddValidationError(ATIVO_NAO_INFORMADO);
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar Bolsa
        /// </summary>
        private bool ValidarBolsa()
        {
            Ordens.BusinessLogic.Bolsa blBolsa = new Ordens.BusinessLogic.Bolsa();

            //Verifica se houve alteração do codigo da bolsa
            if (EntityToValidate.CodigoBolsa != _ordemOriginal.CodigoBolsa)
            {
                Ordens.BusinessEntity.Bolsa bolsa = new Ordens.BusinessEntity.Bolsa
                {
                    Codigo = EntityToValidate.CodigoBolsa
                };

                //Verifica se bolsa existe
                if (blBolsa.ConsultarBolsaCodigo(bolsa) == null)
                    base.AddValidationError(BOLSA_INEXISTENTE);
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar Carteira
        /// </summary>
        private bool ValidarCarteira()
        {
            Carteira.BusinessLogic.Carteira blCarteira = new Carteira.BusinessLogic.Carteira();
            Carteira.BusinessEntity.Parameter.ValidarCarteiraMercado paramValidarCarteiraMercado = null;

            //Verificar se houve alteração
            if (EntityToValidate.Carteira != _ordemOriginal.Carteira)
            {
                //Verifica se ordem é do tipo financiamento
                if (EntityToValidate.TipoOrdem.HasValue &&
                    EntityToValidate.TipoOrdem.Value == BusinessEntity.Enum.TipoOrdem.Financiamento)
                {
                    //Verifica se carteira é diferende de 0
                    if (EntityToValidate.Carteira != 0)
                        base.AddValidationError(CARTEIRA_INVALIDA);
                }
                else
                {
                    //Verifica se ativo informado é POP e a Bolsa é Bovespa
                    if (!string.IsNullOrEmpty(EntityToValidate.CodigoISIN) &&
                        EntityToValidate.CodigoISIN.Substring(6, 2).Equals("PP") &&
                        EntityToValidate.CodigoBolsa == "1")
                    {
                        //Verifica se carteira é diferente de 277
                        if (EntityToValidate.Carteira != 277)
                            base.AddValidationError(CARTEIRA_INVALIDA);
                    }
                    else
                    {
                        //Verifica se carteira foi informada
                        if (EntityToValidate.Carteira.HasValue)
                        {
                            paramValidarCarteiraMercado = new Carteira.BusinessEntity.Parameter.ValidarCarteiraMercado()
                            {
                                CodigoBolsa = EntityToValidate.CodigoBolsa,
                                CodigoCarteira = EntityToValidate.Carteira.HasValue ? EntityToValidate.Carteira.Value : 0,
                                CodigoMercado = (Carteira.BusinessEntity.Enum.TipoMercado?)EntityToValidate.Mercado,
                                NaturezaOperacao = (Carteira.BusinessEntity.Enum.TipoNaturezaOperacao?)EntityToValidate.NaturezaOperacao
                            };

                            //Verifica se carteira informada existe
                            if (!blCarteira.ValidarCarteiraMercado(paramValidarCarteiraMercado))
                                base.AddValidationError(CARTEIRA_INVALIDA);
                        }
                        else
                        {
                            base.AddValidationError(CARTEIRA_NAO_INFORMADA);
                        }
                    }
                }
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar cliente
        /// </summary>
        private bool ValidarCliente()
        {
            Parametro.BusinessLogic.Parametro blParametro = new Parametro.BusinessLogic.Parametro();
            Parametro.BusinessEntity.Parametro paramParametro = null;

            //Verificar se cliente foi informado
            if (EntityToValidate.CodigoCliente != null && EntityToValidate.CodigoCliente != 0)
            {
                //Verifica se houve alteração do cliente
                if (EntityToValidate.CodigoCliente != _ordemOriginal.CodigoCliente)
                {
                    //Verifica se usuário possui acesso para alteração do cliente
                    if (AuthorizationContext.Current.CheckUserAccess("ACLI", "ORD"))
                    {
                        //Verifica se ordem é administrada concorrente
                        if (_ordemOriginal.IndicadorOrdemAdmConcorrente.HasValue && _ordemOriginal.IndicadorOrdemAdmConcorrente.Value)
                        {
                            base.AddValidationError(ORDEM_ADMINISTRADA_CONCORRENTE);
                        }
                        else
                        {
                            //Obtem o cliente
                            this.ObterCliente();

                            //Verifica se cliente foi encontrado
                            if (_cliente != null)
                            {
                                //Verifica se cliente é ativo
                                if (_cliente.Situacao.HasValue && _cliente.Situacao.Value == Cliente.BusinessEntity.Enum.TipoSituacao.Ativo)
                                {
                                    paramParametro = blParametro.ObterParametro();

                                    //Verificar se foi parametrizada obrigatoriedade do dígito verificador do cliente
                                    if (paramParametro != null && paramParametro.IndicadorDigitoCliente == "S")
                                    {
                                        //Verificar se digito do cliente foi informado
                                        if (EntityToValidate.DigitoCliente != null)
                                        {
                                            //Verificar se digito informado é igual ao digito cadastrado
                                            if (Convert.ToInt32(EntityToValidate.DigitoCliente) == _cliente.Digito)
                                            {
                                                //Verificar se o sistema foi parametrizado para verificação de bloqueio de cliente
                                                if (paramParametro.BloqueioClientes)
                                                {
                                                    //Validar se cliente da ordem está bloqueado
                                                    this.VerificarClienteBloqueado();
                                                }
                                            }
                                        }
                                        else
                                        {
                                            base.AddValidationError(CLIENTE_INVALIDO);
                                        }
                                    }
                                }
                                else
                                {
                                    base.AddValidationError(CLIENTE_INVALIDO);
                                }
                            }
                            else
                            {
                                base.AddValidationError(CLIENTE_INVALIDO);
                            }
                        }
                    }
                    else
                    {
                        base.AddValidationError(USUARIO_NAO_AUTORIZADO_ALTERAR_CLIENTE);
                    }
                }
            }
            else
            {
                base.AddValidationError(CLIENTE_NAO_INFORMADO);
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar Data Validade
        /// </summary>
        private bool ValidarDataValidade()
        {
            // Verificar datas
            if (EntityToValidate.DataValidade != _ordemOriginal.DataValidade &&
                EntityToValidate.DataValidade < _ordemOriginal.DataOrdem)
            {
                base.AddValidationError(DATA_INVALIDA);

                return false;
            }

            return true;
        }

        /// <summary>
        /// Validar dolar
        /// </summary>
        private bool ValidarDolar()
        {
            // Verificar se o valor dolar foi alterado
            if (EntityToValidate.ValorDolar != _ordemOriginal.ValorDolar)
            {
                //Verificar se valor dolar é menor ou igual a zero
                if (EntityToValidate.ValorDolar <= 0)
                    base.AddValidationError(DOLAR_INVALIDO);
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar mercado
        /// </summary>
        private bool ValidarMercado()
        {
            int termoSecundario = 0;
            string termoSecundarioObtido = string.Empty;


            //Verificar se ordem é do tipo financiamento
            if (EntityToValidate.TipoOrdem.HasValue &&
                EntityToValidate.TipoOrdem.Value == BusinessEntity.Enum.TipoOrdem.Financiamento)
            {
                //Verificar se mercado é do tipo termo
                if (EntityToValidate.Mercado.HasValue &&
                    EntityToValidate.Mercado.Value == BusinessEntity.Enum.TipoMercado.Termo)
                {
                    // Verificar se o ativo contém o 'T' de termo
                    if (!string.IsNullOrEmpty(EntityToValidate.Ativo) &&
                        EntityToValidate.Ativo.EndsWith("T"))
                    {
                        //Localizar o valor do termo secundário
                        termoSecundarioObtido = EntityToValidate.Ativo.Substring(EntityToValidate.Ativo.Length - 3, 2);
                    }

                    //Verificar se o termo secundário foi encontrado e se é maior que 50
                    if (!string.IsNullOrEmpty(termoSecundarioObtido) &&
                        int.TryParse(termoSecundarioObtido, out termoSecundario) &&
                        termoSecundario > 50)
                    {
                        EntityToValidate.PrazoVencimentoTermo = null;
                    }
                    else
                    {
                        //Verificar se o prazo de venciamento do termo é menor ou igual a zero
                        if (EntityToValidate.PrazoVencimentoTermo <= 0)
                        {
                            base.AddValidationError(PRAZO_VENCIMENTO_NEGATIVO);
                        }
                    }
                }
                else
                {
                    base.AddValidationError(MERCADO_NAO_TERMO);
                }
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar operador
        /// </summary>
        private bool ValidarOperador()
        {
            Usuario.BusinessLogic.Usuario blUsuario = new Usuario.BusinessLogic.Usuario();
            Usuario.BusinessEntity.Parameter.FiltroUsuario paramFiltroUsuario = null;
            List<Usuario.BusinessEntity.Usuario> usuarios = null;
            Operador.BusinessLogic.Operador blOperador = new Operador.BusinessLogic.Operador();
            Operador.BusinessEntity.Parameter.FiltroOperador paramFiltroOperador = null;
            List<Operador.BusinessEntity.Operador> operadores = null;

            paramFiltroOperador = new Operador.BusinessEntity.Parameter.FiltroOperador
            {
                CodigoOperador = AuthorizationContext.Current.UserId
            };

            //Consulta operadores
            operadores = blOperador.ConsultarOperadores(paramFiltroOperador);

            // Verifica se usuário conectado é operador
            if (operadores != null && operadores.Count > 0)
            {
                //Verificar se usuário conectado é operador ponta de mesa
                if (operadores[0].IndicadorPontaMesa.HasValue && operadores[0].IndicadorPontaMesa.Value)
                {
                    EntityToValidate.CodigoOperador = AuthorizationContext.Current.UserId;
                }
                else
                {
                    //Verificar se código do operador informado é diferente do código do usuário logado
                    if (EntityToValidate.CodigoOperador != AuthorizationContext.Current.UserId)
                    {
                        paramFiltroOperador = new Operador.BusinessEntity.Parameter.FiltroOperador
                        {
                            CodigoOperador = EntityToValidate.CodigoOperador
                        };

                        //Consultar operadores
                        operadores = blOperador.ConsultarOperadores(paramFiltroOperador);

                        // Verificar se operador informado é válido
                        if (operadores == null || operadores.Count == 0)
                        {
                            base.AddValidationError(OPERADOR_INVALIDO);

                            return false;
                        }
                    }
                }

                paramFiltroUsuario = new Usuario.BusinessEntity.Parameter.FiltroUsuario()
                {
                    Codigo = EntityToValidate.CodigoOperador,
                    Operador = true
                };

                //Consulta usuários
                usuarios = blUsuario.ConsultarUsuarios(paramFiltroUsuario);

                //Verifica se usuário foi encontrado e se usuário está bloqueado
                if (usuarios != null &&
                    usuarios.Count > 0 &&
                    usuarios[0].Bloqueado.HasValue &&
                    usuarios[0].Bloqueado.Value)
                {
                    base.AddValidationError(USUARIO_BLOQUEADO);
                }
            }
            else
            {
                base.AddValidationError(USUARIO_NAO_OPERADOR);
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar percentual de corretagem
        /// </summary>
        private bool ValidarPercentualCorretagem()
        {
            if (_cliente == null)
                this.ObterCliente();
            
            //Verificar se Percentual de corretagem foi alterado
            if (EntityToValidate.PercentualCorretagem != _ordemOriginal.PercentualCorretagem)
            {
                //Verificar se usuário possui permissão para alterar o percentual de corretagem
                if (AuthorizationContext.Current.CheckUserAccess("ARED", "ORD"))
                {
                    //Verificar se percentual de corretagem foi informado
                    if (EntityToValidate.PercentualCorretagem != null)
                    {
                        //Verificar se percentual corretagem total do cliente é igual a zero
                        if (_cliente.PercentualTotal == 0)
                        {
                            //Verificar se percentual de corretagem maior ou igual a -100
                            if (EntityToValidate.PercentualCorretagem < -100)
                            {
                                base.AddValidationError(PERCENTUAL_CORRETAGEM_INVALIDO);
                            }
                        }
                        else
                        {
                            //Verificar se percentual de corretagem maior ou igual a zero
                            if (EntityToValidate.PercentualCorretagem < 0)
                            {
                                base.AddValidationError(PERCENTUAL_CORRETAGEM_INVALIDO);
                            }
                        }
                    }
                    else
                    {
                        base.AddValidationError(PERCENTUAL_CORRETAGEM_NAO_INFORMADO);
                    }
                }
                else
                {
                    base.AddValidationError(USUARIO_NAO_AUTORIZADO_ALTERAR_PERCENTUAL_CORRETAGEM);
                }
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar preço
        /// </summary>
        private bool ValidarPreco()
        {
            //Verificar se Tipo da Ordem é Limitada ou OnStop
            if ((EntityToValidate.TipoOrdem.HasValue &&
                EntityToValidate.TipoOrdem.Value == BusinessEntity.Enum.TipoOrdem.Limitada) ||
                (EntityToValidate.TipoOrdem.HasValue &&
                EntityToValidate.TipoOrdem.Value == BusinessEntity.Enum.TipoOrdem.OnStop))
            {
                //Verificar se preço da ordem é positivo
                if (EntityToValidate.Preco <= 0)
                {
                    base.AddValidationError(PRECO_ORDEM_INVALIDO);
                }
            }
            else
            {
                //TODO: EA
                //Verificar se preço da ordem é zero
                if (EntityToValidate.Preco != 0)
                {
                    base.AddValidationError(PRECO_ORDEM_INVALIDO);
                }
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar quantidade
        /// </summary>
        private bool ValidarQuantidade()
        {
            Titulo.BusinessLogic.Titulo blTitulo = new Titulo.BusinessLogic.Titulo();
            Titulo.BusinessEntity.Parameter.ConsultarLoteMinimoNegociacao paramConsultarLoteMinimoNegociacao = null;
            Int32 loteMinimoNegociacao = 0;


            //Verificar se quantidade foi alterada
            if (EntityToValidate.Quantidade != _ordemOriginal.Quantidade)
            {
                //Verificar se usuário possui permissão para alterar a quantidade
                if (AuthorizationContext.Current.CheckUserAccess("AQTD", "ORD"))
                {
                    //Verificar se Tipo da ordem é financiamento
                    if (EntityToValidate.TipoOrdem.HasValue &&
                        EntityToValidate.TipoOrdem.Value == BusinessEntity.Enum.TipoOrdem.Financiamento)
                    {
                        //Verificar se quantidade é diferente de 0
                        if (!EntityToValidate.Quantidade.HasValue || EntityToValidate.Quantidade.Value != 0)
                        {
                            base.AddValidationError(QUANTIDADE_DIFEENTE_ZERO);
                            return false;
                        }
                    }
                    else
                    {

                        //Verifica se quantidade é maior que zero
                        if (EntityToValidate.Quantidade.HasValue &&
                            EntityToValidate.Quantidade.Value > 0)
                        {
                            paramConsultarLoteMinimoNegociacao = new Titulo.BusinessEntity.Parameter.ConsultarLoteMinimoNegociacao
                            {
                                _DataPregao = _informacoesMovimento.DataMovimento,
                                _Titulo = EntityToValidate.Ativo
                            };

                            //Consulta lote mínimo para negociação
                            loteMinimoNegociacao = blTitulo.ConsultarLoteMinimoNegociacao(paramConsultarLoteMinimoNegociacao);

                            //Verificar se quantidade da ordem é múltiplo do lote mínimo
                            if (loteMinimoNegociacao != 0 &&
                                (EntityToValidate.Quantidade % loteMinimoNegociacao) != 0)
                            {
                                base.AddValidationError(QUANTIDADE_NAO_MULTIPL0);

                                return false;
                            }
                            else
                            {
                                //Verificar se quantidade foi reduzida e ordem já está distribuida
                                if (EntityToValidate.Quantidade.HasValue &&
                                    _ordemOriginal.Quantidade.HasValue &&
                                    EntityToValidate.Quantidade.Value < _ordemOriginal.Quantidade.Value &&
                                    _ordemOriginal.Distribuida.HasValue &&
                                    _ordemOriginal.Distribuida.Value)
                                {
                                    base.AddValidationError(ORDEM_REDUZIDA_E_DISTRIBUIDA);

                                    return false;
                                }
                            }
                        }
                        else
                        {
                            base.AddValidationError(QUANTIDADE_DIFEENTE_ZERO);

                            return false;
                        }
                    }
                }
                else
                {
                    base.AddValidationError(USUARIO_NAO_AUTORIZADO_ALTERAR_QUANTIDADE);
                }
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Verificar o diagrama de atividade
        /// BusinessRulesValidation/ValidadorAlteracaoOrdem.ValidarSituacao()
        /// </summary>
        private bool ValidarSituacao()
        {
            //Verifica se houve alteração na situação
            if (EntityToValidate.Situacao != _ordemOriginal.Situacao)
            {
                //Verifica se situacao original da ordem é Demais
                if (_ordemOriginal.Situacao == BusinessEntity.Enum.SituacaoOrdem.Demais)
                {
                    //Verifica se situação é alterada para Home Broker
                    if (EntityToValidate.Situacao != BusinessEntity.Enum.SituacaoOrdem.HomeBroker)
                        base.AddValidationError(ALTERACAO_SITUACAO_INVALIDA);
                }
                else
                {
                    //Verifica se Situação original da ordem é Home Broker
                    if (_ordemOriginal.Situacao == BusinessEntity.Enum.SituacaoOrdem.HomeBroker)
                    {
                        //Verifica se situação é alterada para Demais
                        if (EntityToValidate.Situacao != BusinessEntity.Enum.SituacaoOrdem.Demais)
                        {
                            base.AddValidationError(ALTERACAO_SITUACAO_INVALIDA);
                        }
                    }
                }
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar tipo ordem
        /// </summary>
        private bool ValidarTipoOrdem()
        {
            //Verifica se tipo ordem foi alterado
            if (EntityToValidate.TipoOrdem != _ordemOriginal.TipoOrdem)
            {
                //Verifica se ordem é administrada concorrente
                if (_ordemOriginal.IndicadorOrdemAdmConcorrente.HasValue &&
                    _ordemOriginal.IndicadorOrdemAdmConcorrente.Value)
                {
                    base.AddValidationError(ORDEM_ADMINISTRADA_CONCORRENTE_TIPO_ORDEM);
                }
                else
                {
                    //Verifica se tipo da ordem é financiamento
                    if (_ordemOriginal.TipoOrdem.HasValue &&
                        _ordemOriginal.TipoOrdem.Value == BusinessEntity.Enum.TipoOrdem.Financiamento)
                    {
                        //Validar e configurar ordem do tipo financiamento
                        this.ValidarTipoOrdemFinanciamento();
                    }
                }
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Validar Tipo Ordem Financiamento
        /// </summary>
        private bool ValidarTipoOrdemFinanciamento()
        {
            //Assumir nulo para a natureza da operação            
            EntityToValidate.PrazoVencimentoTermo = null;

            //Verificar se percentual de financiamento é maior ou igual a zero e menor igual a 100
            //Se não for, adicionar exceção
            if (!EntityToValidate.PercentualFinanciamento.HasValue ||
                EntityToValidate.PercentualFinanciamento.Value < 0 ||
                EntityToValidate.PercentualFinanciamento.Value > 100)
            {
                base.AddValidationError(INTERVALO_PERCENTUAL_FINANCIAMENTO_INCORRETO);
            }

            //Verifica se valor do financiamento foi informado e se 
            //o valor do financiamento é maior ou igual a zero
            if (!EntityToValidate.ValorFinanciamento.HasValue ||
                EntityToValidate.ValorFinanciamento < 0)
            {
                base.AddValidationError(VALOR_FINANCIAMENTO_NEGATIVO);
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Processo responsável por validar as alterações em uma ordem.
        /// </summary>
        public void Validate()
        {
            BusinessEntity.ChaveOrdem chaveOrdem = null;

            chaveOrdem = new BusinessEntity.ChaveOrdem
            {
                DataOrdem = EntityToValidate.DataOrdem,
                NumeroOrdem = EntityToValidate.NumeroOrdem,
                NumeroOrdemSubSequencia = EntityToValidate.NumeroOrdemSubSequencia
            };

            //Obter dados atuais da ordem a ser alterada
            this._ordemOriginal = raManutencaoOrdens.ObterOrdem(chaveOrdem);

            //Verifica se Ordem está cancelada
            if (_ordemOriginal.Situacao == BusinessEntity.Enum.SituacaoOrdem.Cancelada)
            {
                base.AddValidationError(ORDEM_CANCELADA);
            }
            else
            {
                //Valida operador
                if (this.ValidarOperador())
                {
                    //Verifica se data de validade da ordem é menor que a data do movimento
                    if (_ordemOriginal.DataValidade < _informacoesMovimento.DataMovimento)
                    {
                        //Verifica se usuário possui permissão para alterar ordem com esta característica
                        if (!AuthorizationContext.Current.CheckUserAccess("D1SIM", "ORD"))
                        {
                            base.AddValidationError(USUARIO_NAO_AUTORIZADO_ALTERAR_ORDEM);
                            return;
                        }
                    }

                    if (_ordemOriginal.IndicadorOrdemAdmConcorrente != EntityToValidate.IndicadorOrdemAdmConcorrente)
                    {
                        base.AddValidationError(ADMINISTRADA_CONCORRENTE_MODIFICADA);
                    }
                    else
                    {
                        //Valida alteração na situação da ordem
                        if (this.ValidarSituacao())
                        {
                            //Valida alteração do cliente
                            if (this.ValidarCliente())
                            {
                                //Valida alteração no percentual de corretagem
                                if (this.ValidarPercentualCorretagem())
                                {
                                    //Valida alteração do tipo da ordem
                                    if (this.ValidarTipoOrdem())
                                    {
                                        //Valida mercado
                                        if (this.ValidarMercado())
                                        {
                                            //Valida ativo
                                            if (this.ValidarAtivo())
                                            {
                                                //Valida bolsa
                                                if (this.ValidarBolsa())
                                                {
                                                    //Valida preco
                                                    if (this.ValidarPreco())
                                                    {
                                                        //Valida carteira
                                                        if (this.ValidarCarteira())
                                                        {
                                                            //Validar quantidade anexo
                                                            if (this.ValidarQuantidadeAnexo())
                                                            {
                                                                //Valida quantidade
                                                                if (this.ValidarQuantidade())
                                                                {
                                                                    //Validar alteração do dolar
                                                                    if (this.ValidarDolar())
                                                                    {
                                                                        //Valida alteração na data de validade
                                                                        if (this.ValidarDataValidade())
                                                                        {
                                                                            //Configura o tipo de distribuição permitida
                                                                            this.ConfigurarTipoDistribuicao();

                                                                            //Configura ordem com valores padroes
                                                                            this.ConfigurarOrdem();
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Verificar cliente bloqueado
        /// </summary>
        private bool VerificarClienteBloqueado()
        {
            BusinessEntity.Resultado resultado = null;

            //Verifica se data de validade da ordem é menor que a data do sistema
            if (EntityToValidate.DataValidade < _informacoesMovimento.DataMovimento)
            {
                resultado = raManutencaoOrdens.VerificarClienteBloqueado(EntityToValidate, BusinessEntity.Enum.TipoValidacaoClienteBloqueado.PorDataValidade);
            }
            else
            {
                resultado = raManutencaoOrdens.VerificarClienteBloqueado(EntityToValidate, BusinessEntity.Enum.TipoValidacaoClienteBloqueado.PorDataPregao);
            }

            //Verifica se existe bloqueio para o cliente
            if (resultado != null && !resultado.Sucesso)
            {
                if (resultado.CodigoErro == -1)
                    base.AddValidationError(ERRO_INESPERADO_VERIFICAR_CLIENTE_BLOQUEADO);
                else
                    this.TratarExcecoes(resultado);
            }

            return base.ErrorsList.Count == 0;
        }

        /// <summary>
        /// Obter Cliente
        /// </summary>
        private void ObterCliente()
        {
            Cliente.BusinessLogic.Cliente blCliente = new Cliente.BusinessLogic.Cliente();
            Cliente.BusinessEntity.Parameter.FiltroCliente paramFiltroCliente = null;

            paramFiltroCliente = new Cliente.BusinessEntity.Parameter.FiltroCliente
            {
                Codigo = EntityToValidate.CodigoCliente
            };

            _cliente = blCliente.ObterCliente(paramFiltroCliente);
        }

        /// <summary>
        /// Validar quantidade anexo
        /// </summary>
        private bool ValidarQuantidadeAnexo()
        {            
            if (EntityToValidate.QuantidadeAnexoIV < 0 || EntityToValidate.QuantidadeAnexoV < 0)
            {
                base.AddValidationError(QUANTIDADE_ANEXOIV_MAIOR_IGUAL_ZERO);
            }

            if ((EntityToValidate.QuantidadeAnexoV + EntityToValidate.QuantidadeAnexoIV) > EntityToValidate.Quantidade)
            {
                base.AddValidationError(SOMA_QUANTIDADE_ANEXO_MAIOR_QUANTIDADE);
            }

            return base.ErrorsList.Count == 0;
        }

        #endregion
    }
}
